﻿using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SHKF.B2C.MeiTuanShanGou.Model.Dto;
using SHKF.B2C.MeiTuanShanGou.Model.Dto.Medicine;
using SHKF.B2C.MeiTuanShanGou.Model.Dto.Order;
using SHKF.B2C.MeiTuanShanGou.Model.Dto.OrderDetail;
using SHKF.B2C.MeiTuanShanGou.Model.Dto.OrderIdByDaySeq;
using SHKF.B2C.MeiTuanShanGou.Model.Dto.OrderRefundDetail;
using SHKF.B2C.MeiTuanShanGou.Model.Dto.Poi;
using SHKF.B2C.MeiTuanShanGou.Model.Dto.Token;
using SHKF.B2C.Model;
using SHKF.B2C.Model.Dto;
using SHKF.B2C.Model.Dto.Center;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace SHKF.B2C.MeiTuanShanGou.Network
{
    /// <summary>
    /// 美团闪购
    /// </summary>
    public class HttpClientMeiTuanShanGou : HttpClient
    {
        //--------------------------------------------------Base
        public long timestamp;
        public string access_token = "";
        public long app_poi_code = 0;
        protected string app_id = "7311";
        protected string app_secret = "69720fafdef5ba5f78c4548dbb827629";
        private string urlToken = "api/v1/oauth/authorize";
        private string urlRefreshToken = "/api/v1/oauth/token";

        //--------------------------------------------------门店 
        private string urlPoiOpen = "/api/v1/poi/open";         //门店设置为营业状态
        private string urlPoiMget = "/api/v1/poi/mget";         //批量获取门店详细信息
        private string urlPoiGetIds = "/api/v1/poi/getids";     //获取应用已绑定门店的三方门店ID

        //--------------------------------------------------商品
        private string urlPostMedicineIsSoldOut = "/api/v1/medicine/isSoldOut";
        private string urlGetMedicineList = "/api/v1/medicine/list";            //查询门店药品列表
        private string urlPostMedicineSave = "/api/v1/medicine/save";           //保存药品
        private string urlPostMedicineDelete = "/api/v1/medicine/delete";       //保存药品
        private string urlGetMedicineCatList = "/api/v1/medicineCat/list";      //查询门店药品分类列表
        private string urlPostMedicineStock = "/api/v1/medicine/stock";         //更新库存
        private string urlPostUpdatePrice = "/api/v1/medicine/price";           //更新价格
        private string urlGetOrderQuery = "/api/v1/order/getOrderDetail";          //定单明细
        private string urlGetOrderIdByDaySeq = "/api/v1/ecommerce/order/getOrderIdByDaySeq";        //根据流水号获取订单ID（分段）
        private string urlGetOrderRefundDetail = "/api/v1/ecommerce/order/getOrderRefundDetail";    //获取订单退款记录

        //--------------------------------------------------定单   
        //private string urlGetOrderDetail = "/api/v1/order/getOrderDetail";                    //获取订单详细信息    
        private string urlOrderLogisticsPush = "/api/v1/order/logistics/push";                  //下发美团配送订单
        private string urlOrderLogisticsCancel = "/api/v1/order/logistics/cancel";              //下发美团配送订单


        private readonly ILogger<HttpClientMeiTuanShanGou> logger;


        public HttpClientMeiTuanShanGou(ILogger<HttpClientMeiTuanShanGou> logger)
        {
            this.logger = logger;
            base.BaseAddress = new Uri("https://waimaiopen.meituan.com");
        }


        public long GetTimeStamp()
        {
            DateTime now = DateTime.Now;
            this.timestamp = DateTimeUtil.DateTimeToTimeStamp(now);
            return timestamp;
        }

        public async Task<TokenMeiTuanDto> GetToken(long timestamp)
        {
            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("app_id", this.app_id);
            values.Add("app_poi_code", this.app_poi_code);
            values.Add("response_type", "token");
            values.Add("timestamp", timestamp);

            string url = this.CreateSortParams(values);

            string urlMd5 = base.BaseAddress + urlToken + "?" + url;
            string sig = this.md5(urlMd5);
            string urlGet = urlMd5 + $"&sig={sig}";
            TokenMeiTuanDto requestToken = null;

            //从接口获取d
            HttpResponseMessage httpResponseMessage = await base.GetAsync(urlGet);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                requestToken = await httpResponseMessage.Content.ReadAsAsync<TokenMeiTuanDto>();
                if (requestToken.status == 0)
                {
                    this.access_token = requestToken.access_token;
                }
                else
                {
                    requestToken.error = new Error()
                    {
                        code = requestToken.status,
                        msg = requestToken.message
                    };

                    this.WriteInformation("GetToken", $"status:{requestToken.status} || msg:{requestToken.message}");
                }
            }

            return requestToken;
        }

        public async Task<TokenMeiTuanDto> PostRefreshToken(string refresh_token, long timestamp)
        {
            TokenMeiTuanDto requestToken = null;
            try
            {
                //string para = base.BaseAddress + this.urlRefreshToken + "?";
                //para += $"app_id={app_id}";
                //para += $"&app_poi_code={app_poi_code}";
                //para += $"&grant_type=refresh_token";
                //para += $"&refresh_token={refresh_token}";
                //para += $"&timestamp={timestamp}";

                //string sig = this.md5(para + $"{app_secret}");

                //var paras = new List<KeyValuePair<string, string>>();
                //paras.Add(new KeyValuePair<string, string>("app_id", this.app_id));
                //paras.Add(new KeyValuePair<string, string>("app_poi_code", this.app_poi_code.ToString()));
                //paras.Add(new KeyValuePair<string, string>("grant_type", "refresh_token"));
                //paras.Add(new KeyValuePair<string, string>("refresh_token", refresh_token));
                //paras.Add(new KeyValuePair<string, string>("timestamp", timestamp.ToString()));
                //paras.Add(new KeyValuePair<string, string>("sig", sig));

                //var content = new FormUrlEncodedContent(paras);

                Dictionary<string, object> values = new Dictionary<string, object>();
                values.Add("app_id", this.app_id);
                values.Add("app_poi_code", this.app_poi_code);
                values.Add("timestamp", timestamp);
                values.Add("grant_type", "refresh_token");
                values.Add("refresh_token", refresh_token);
                string url = base.BaseAddress.OriginalString + urlRefreshToken + "?" + this.CreateSortParams(values);
                //创建签名
                string sig = this.md5(url);
                string urlPost = base.BaseAddress.OriginalString + urlRefreshToken + $"?sig={sig}&app_id={this.app_id}&timestamp={this.timestamp}";

                HttpContent httpContent = this.CreateBody(values);
                HttpResponseMessage httpResponseMessage = await base.PostAsync(urlPost, httpContent);

                //HttpResponseMessage httpResponseMessage = await base.PostAsync(urlRefreshToken, content);

                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string error = await httpResponseMessage.Content.ReadAsStringAsync();
                    DataDto errorDataDto = JsonConvert.DeserializeObject<DataDto>(error);
                    if (errorDataDto != null && errorDataDto.data != null && errorDataDto.error != null)
                    {
                        this.WriteErrorData(errorDataDto.error);
                    }
                    else
                    {
                        requestToken = await httpResponseMessage.Content.ReadAsAsync<TokenMeiTuanDto>();
                        this.access_token = requestToken.access_token;
                    }
                }
                else
                {
                    TokenErrorDto error = await httpResponseMessage.Content.ReadAsAsync<TokenErrorDto>();

                    this.WriteInformation("PostRefreshToken", $"error:{error.error} status:{error.status} message:{error.message} path: {error.path}");
                }

            }
            catch (Exception ex)
            {
                this.WriteException("postRefreshToken", ex);
            }
            return requestToken;
        }


        #region 门店类
        public async Task<string> postPoiOpen()
        {
            string para = this.urlPoiOpen + "?";
            para += getBaseUrl();
            para += $"&timestamp={timestamp}";

            string sig = this.md5(para + $"{app_secret}");

            var paras = new List<KeyValuePair<string, string>>();
            paras.Add(new KeyValuePair<string, string>("access_token", access_token));
            paras.Add(new KeyValuePair<string, string>("app_id", this.app_id));
            paras.Add(new KeyValuePair<string, string>("app_poi_code", this.app_poi_code.ToString()));
            paras.Add(new KeyValuePair<string, string>("timestamp", timestamp.ToString()));
            paras.Add(new KeyValuePair<string, string>("sig", sig));

            var content = new FormUrlEncodedContent(paras);
            string result = "";
            HttpResponseMessage httpResponseMessage = await base.PostAsync(urlPoiOpen, content);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                result = await httpResponseMessage.Content.ReadAsStringAsync();
            }
            else
            {
                result = await httpResponseMessage.Content.ReadAsStringAsync();
            }

            return "";
        }


        /// <summary>
        /// 批量获取门店详细信息
        /// </summary>
        /// <param name="app_poi_codes"></param>
        /// <returns></returns>
        public async Task<PoiListDto> MGet(string app_poi_codes)
        {
            string url = base.BaseAddress.OriginalString + urlPoiMget + "?";
            url += this.getBaseUrl();
            url += $"&app_poi_codes={app_poi_codes}";
            url += $"&timestamp={this.timestamp}";

            string sig = this.md5(url + $"{app_secret}");
            url += $"&sig={sig}";
            PoiListDto dto = null;

            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();
                try
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<PoiListDto>();
                }
                catch
                {
                    dto = new PoiListDto();
                    ErrorDto errorData = JsonConvert.DeserializeObject<ErrorDto>(result);
                    dto.error = errorData.error;
                    this.WriteInformation("GetOrderDaySeq", $"code:{dto.error.code}  msg:{dto.error.msg}");
                }
            }

            return dto;
        }

        /// <summary>
        /// 获取应用已绑定门店的三方门店ID
        /// </summary>
        /// <returns></returns>
        public async Task<PoiIdsDto> GetIds()
        {
            string url = base.BaseAddress.OriginalString + urlPoiGetIds + "?";
            url += this.getBaseUrl();
            url += $"&timestamp={this.timestamp}";

            string sig = this.md5(url + $"{app_secret}");
            url += $"&sig={sig}";
            PoiIdsDto dto = null;

            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();
                try
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<PoiIdsDto>();
                }
                catch
                {
                    dto = new PoiIdsDto();
                    ErrorDto errorData = JsonConvert.DeserializeObject<ErrorDto>(result);
                    dto.error = errorData.error;
                    this.WriteInformation("GetOrderDaySeq", $"code:{dto.error.code}  msg:{dto.error.msg}");
                }
            }

            return dto;
        }

        #endregion

        #region 商品

        /// <summary>
        /// 药品分类列表
        /// </summary>
        /// <returns></returns>
        public async Task<MedicineCatListDto> GetCatList()
        {
            string url = base.BaseAddress.OriginalString + this.urlGetMedicineCatList + "?";
            url += this.getBaseUrl();
            url += $"&timestamp={timestamp}";

            string sig = this.md5(url + $"{app_secret}");
            url += $"&sig={sig}";
            MedicineCatListDto dto = null;

            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();
                try
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<MedicineCatListDto>();
                }
                catch (Exception ex)
                {
                    dto = new MedicineCatListDto();
                    DataDto errorData = JsonConvert.DeserializeObject<DataDto>(result);
                    dto.error = errorData.error;
                    this.WriteInformation("CatList", $"code:{dto.error.code}  msg:{dto.error.msg} ex:{ex.Message}");
                }
            }
            else
            {
                dto = new MedicineCatListDto();
                dto.error = CreateHttpError(httpResponseMessage);
                this.WriteErrorData(dto.error);
            }
            return dto;
        }

        /// <summary>
        /// 保存商品
        /// </summary>
        /// <param name="medicine"></param>
        /// <returns></returns>
        public async Task<DataDto> MedicineSave(MedicineInfo medicine)
        {
            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("app_medicine_code", medicine.app_medicine_code);
            values.Add("category_name", medicine.category_name);
            values.Add("is_sold_out", medicine.is_sold_out);
            values.Add("medicine_no", medicine.medicine_no);
            values.Add("price", medicine.price);
            values.Add("sequence", medicine.sequence);
            values.Add("spec", medicine.spec);
            values.Add("stock", medicine.stock);
            values.Add("upc", medicine.upc);
            values.Add("name", medicine.name);
            values.Add("medicine_type", medicine.medicine_type);

            //string url = base.BaseAddress.OriginalString + this.urlPostMedicineSave + "?";
            //url += $"access_token={this.access_token}";
            //url += $"&app_id={this.app_id}";
            //url += $"&app_medicine_code={medicine.app_medicine_code}";
            //url += $"&app_poi_code={this.app_poi_code}";
            //if(!string.IsNullOrEmpty(medicine.category_code))
            //{
            //    url += $"&category_code={medicine.category_code}";
            //}

            //url += $"&category_name={medicine.category_name}";
            ////url += $"&ctime={medicine.ctime}";
            //url += $"&is_sold_out={medicine.is_sold_out}";
            //url += $"&medicine_no={medicine.medicine_no}";
            //url += $"&price={medicine.price}";
            ////url += $"&medicine_type={medicine.medicine_type}";
            ////url += $"&name={medicine.name}";　
            //url += $"&sequence={medicine.sequence}";
            //url += $"&spec={medicine.spec}";
            //url += $"&stock={medicine.stock}";
            //url += $"&timestamp={this.timestamp}";
            //url += $"&upc={medicine.upc}";
            //url += $"&utime={medicine.utime}";

            //string url2 = "access_token=token_mHM_2lVcr8gTBRbmAxZBHw&app_id=7311&app_medicine_code=623111942&app_poi_code=13587900&category_name=未分类&is_sold_out=0&medicine_no=国食药监械（进）字2013第2661108号&price=28.0&sequence=0&spec=10+2&stock=0&timestamp=1661348816&upc=692709940398469720fafdef5ba5f78c4548dbb827629";
            //string sig = this.md5(url + $"{app_secret}");

            //string sig = this.md5(url2);
            //url += $"&sig={sig}";
            //url2 += $"&sig={sig}";
            DataDto dto = null;
            try
            {

                string postUrl = this.CreatePostUrl(this.urlPostMedicineSave, values);
                HttpContent httpContent = this.CreateBody(values);

                HttpResponseMessage httpResponseMessage = await base.PostAsync(postUrl, httpContent);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string result = await httpResponseMessage.Content.ReadAsStringAsync();
                    try
                    {
                        dto = await httpResponseMessage.Content.ReadAsAsync<DataDto>();
                    }
                    catch
                    {
                        dto = new DataDto();
                        ErrorDto errorData = JsonConvert.DeserializeObject<ErrorDto>(result);
                        dto.error = errorData.error;
                        this.WriteInformation("MedicineSave", $"code:{dto.error.code}  msg:{dto.error.msg}");
                    }
                }
                else
                {
                    dto = new DataDto();
                    dto.error = CreateHttpError(httpResponseMessage);
                    this.WriteErrorData(dto.error);
                }
            }
            catch (Exception ex)
            {
                dto.SetException(ex);
                this.WriteException("MedicineSave", ex);
            }

            return dto;
        }

        /// <summary>
        /// 删除商品
        /// </summary>
        /// <param name="medicine"></param>
        /// <returns></returns>
        public async Task<DataDto> MedicineDelete(long app_poi_code, long app_medicine_code)
        {
            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("app_poi_code", app_poi_code);
            values.Add("app_medicine_code", app_medicine_code);

            DataDto dto = null;
            try
            {
                string postUrl = this.CreatePostUrl(this.urlPostMedicineDelete, values);
                HttpContent httpContent = this.CreateBody(values);

                HttpResponseMessage httpResponseMessage = await base.PostAsync(postUrl, httpContent);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string result = await httpResponseMessage.Content.ReadAsStringAsync();
                    try
                    {
                        dto = await httpResponseMessage.Content.ReadAsAsync<DataDto>();
                    }
                    catch
                    {
                        dto = new DataDto();
                        ErrorDto errorData = JsonConvert.DeserializeObject<ErrorDto>(result);
                        dto.error = errorData.error;
                        this.WriteInformation("MedicineSave", $"code:{dto.error.code}  msg:{dto.error.msg}");
                    }
                }
                else
                {
                    dto = new DataDto();
                    dto.error = CreateHttpError(httpResponseMessage);
                    this.WriteErrorData(dto.error);
                }
            }
            catch (Exception ex)
            {
                dto.SetException(ex);
                this.WriteException("MedicineSave", ex);
            }

            return dto;
        }


        private Error CreateHttpError(HttpResponseMessage httpResponseMessage)
        {
            Error dto = new Error();
            dto.code = -1;
            dto.msg = httpResponseMessage.ToString();
            return dto;
        }

        /// <summary>
        /// 查询门店药品列表
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public async Task<MedicineListDto> GetMedicineList(int offset, int limit)
        {
            string url = base.BaseAddress.OriginalString + this.urlGetMedicineList + "?";
            url += this.getBaseUrl();
            url += $"&limit={limit}";
            url += $"&offset={offset}";
            url += $"&timestamp={timestamp}";

            string sig = this.md5(url + $"{app_secret}");
            url += $"&sig={sig}";

            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("limit", limit);
            values.Add("offset", offset);
            values.Add("app_poi_code", app_poi_code);

            url = CreateGetUrl(this.urlGetMedicineList, values);

            MedicineListDto dto = null;

            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();
                try
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<MedicineListDto>();
                }
                catch
                {
                    dto = new MedicineListDto();
                    DataDto errorData = JsonConvert.DeserializeObject<DataDto>(result);
                    dto.error = errorData.error;
                    this.WriteInformation("GetMedicineList", $"code:{dto.error.code}  msg:{dto.error.msg}");
                }
            }
            else
            {
                dto = new MedicineListDto();
                dto.error = CreateHttpError(httpResponseMessage);
                this.WriteErrorData(dto.error);
            }
            return dto;
        }

        /// <summary>
        /// 药品批量上下架
        /// </summary>
        /// <returns></returns>
        public async Task<IsSoldOutResultDto> PostIsSoldOut(IsSoldOutDto isSoldOutDto)
        {
            //string url = base.BaseAddress.OriginalString + this.urlPostMedicineIsSoldOut + "?";
            //string json = JsonConvert.SerializeObject(isSoldOutDto.medicine_data);
            //url += this.getBaseUrl();
            //url += $"&medicine_data={json}";
            //url += $"&timestamp={this.timestamp}";

            //string sig = this.md5(url + $"{app_secret}");
            //url += $"&sig={sig}";
            IsSoldOutResultDto dto = null;
            try
            {
                string json = JsonConvert.SerializeObject(isSoldOutDto.medicine_data);
                Dictionary<string, object> values = new Dictionary<string, object>();
                values.Add("medicine_data", json);
                string postUrl = this.CreatePostUrl(this.urlPostMedicineIsSoldOut, values);
                HttpContent httpContent = this.CreateBody(values);

                HttpResponseMessage httpResponseMessage = await base.PostAsync(postUrl, httpContent);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string result = await httpResponseMessage.Content.ReadAsStringAsync();
                    try
                    {
                        BaseDataDto data = await httpResponseMessage.Content.ReadAsAsync<BaseDataDto>();
                        dto = new IsSoldOutResultDto();
                        dto.data = data.data;

                        if (dto.data == "ng")
                        {
                            DataDto errorData = JsonConvert.DeserializeObject<DataDto>(result);
                            dto.error = errorData.error;
                            this.WriteInformation("PostIsSoldOut", $"code:{dto.error.code}  msg:{dto.error.msg}");
                        }
                    }
                    catch
                    {
                        dto = new IsSoldOutResultDto();
                        DataDto errorData = JsonConvert.DeserializeObject<DataDto>(result);
                        dto.error = errorData.error;
                        this.WriteInformation("PostIsSoldOut", $"code:{dto.error.code}  msg:{dto.error.msg}");
                    }
                }
                else
                {
                    dto = new IsSoldOutResultDto();
                    dto.error = CreateHttpError(httpResponseMessage);
                    this.WriteErrorData(dto.error);
                }
            }
            catch (Exception ex)
            {
                dto.error = new Error() { code = -1, msg = ex.Message };
            }

            return dto;
        }

        /// <summary>
        /// 批量更新库存
        /// </summary>
        /// <param name="stock"></param>
        /// <returns></returns>
        public async Task<DataDto> Stock(ProductStock stock)
        {
            //string url = base.BaseAddress.OriginalString + this.urlPostMedicineStock + "?";

            //url += this.getBaseUrl();
            //url += $"&medicine_data={json}";
            //url += $"&timestamp={this.timestamp}";

            //string sig = this.md5(url + $"{app_secret}");
            //url += $"&sig={sig}";
            DataDto dto = null;

            string json = "";

            try
            {
                json = JsonConvert.SerializeObject(stock.medicine_data);
                Dictionary<string, object> values = new Dictionary<string, object>();
                values.Add("medicine_data", json);
                string postUrl = this.CreatePostUrl(this.urlPostMedicineStock, values);
                HttpContent httpContent = this.CreateBody(values);

                HttpResponseMessage httpResponseMessage = await base.PostAsync(postUrl, httpContent);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string result = await httpResponseMessage.Content.ReadAsStringAsync();
                    try
                    {
                        BaseDataDto data = await httpResponseMessage.Content.ReadAsAsync<BaseDataDto>();
                        if (data.data == "ng")
                        {
                            dto = new DataDto();
                            if (result.Contains("error"))
                            {
                                ErrorDto errorDto = JsonConvert.DeserializeObject<ErrorDto>(result);
                                dto.error = errorDto.error;
                            }
                            else
                            {
                                MsgDto msgDto = JsonConvert.DeserializeObject<MsgDto>(result);
                                dto.error = new Error { code = -1, msg = msgDto.msg };
                            }
                            this.WriteInformation("Stock", $"code:{dto.error.code}  msg:{dto.error.msg}");
                        }
                        else
                        {
                            dto = new DataDto();
                            dto.data = data.data;
                        }
                    }
                    catch
                    {
                        dto = new DataDto();
                        if (result.Contains("error"))
                        {
                            ErrorDto errorDto = JsonConvert.DeserializeObject<ErrorDto>(result);
                            dto.error = errorDto.error;
                        }
                        else
                        {
                            MsgDto msgDto = JsonConvert.DeserializeObject<MsgDto>(result);
                            dto.error = new Error { code = -1, msg = msgDto.msg };
                        }
                        this.WriteInformation("Stock", $"code:{dto.error.code}  msg:{dto.error.msg}");
                    }
                }
                else
                {
                    dto = new IsSoldOutResultDto();
                    dto.error = CreateHttpError(httpResponseMessage);
                    this.WriteErrorData(dto.error);
                }
            }
            catch (Exception ex)
            {
                dto.error = new Error() { code = -1, msg = ex.Message };
                this.WriteException("Stock", new Exception(ex.Message + $" json:{ json }"));
            }

            return dto;
        }

        /// <summary>
        /// 批量更新价格
        /// </summary>
        /// <param name="medicinePrice"></param>
        /// <returns></returns>
        public async Task<MedicinePriceDto> BatchUpdatePrice(List<MedicinePriceData> objJson)
        {
            MedicinePriceDto dto = null;

            try
            {
                string json = JsonConvert.SerializeObject(objJson);
                Dictionary<string, object> values = new Dictionary<string, object>();
                values.Add("medicine_data", json);
                string postUrl = this.CreatePostUrl(this.urlPostUpdatePrice, values);
                HttpContent httpContent = this.CreateBody(values);

                HttpResponseMessage httpResponseMessage = await base.PostAsync(postUrl, httpContent);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string result = await httpResponseMessage.Content.ReadAsStringAsync();

                    dto = await httpResponseMessage.Content.ReadAsAsync<MedicinePriceDto>();
                    if (dto.data == "ng")
                    {
                        this.WriteInformation("UpdatePrice", $"code:{dto.error.code}  msg:{dto.error.msg}");
                    }
                }
                else
                {
                    dto = new MedicinePriceDto();
                    dto.error = CreateHttpError(httpResponseMessage);
                    this.WriteErrorData(dto.error);
                }
            }
            catch (Exception ex)
            {
                dto.error = new Error() { code = -1, msg = ex.Message };
                this.WriteException("UpdatePrice", ex);
            }
            return dto;
        }

        public async Task<MedicinePriceDto> BatchUpdatePrice(MedicinePrice objJson)
        {
            MedicinePriceDto dto = null;

            try
            {
                string json = JsonConvert.SerializeObject(objJson.medicine_data);
                Dictionary<string, object> values = new Dictionary<string, object>();
                values.Add("medicine_data", json);
                string postUrl = this.CreatePostUrl(this.urlPostUpdatePrice, values);
                HttpContent httpContent = this.CreateBody(values);

                HttpResponseMessage httpResponseMessage = await base.PostAsync(postUrl, httpContent);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string result = await httpResponseMessage.Content.ReadAsStringAsync();

                    dto = await httpResponseMessage.Content.ReadAsAsync<MedicinePriceDto>();
                    if (dto.data == "ng")
                    {
                        this.WriteInformation("UpdatePrice", $"code:{dto.error.code}  msg:{dto.error.msg}");
                    }
                }
                else
                {
                    dto = new MedicinePriceDto();
                    dto.error = CreateHttpError(httpResponseMessage);
                    this.WriteErrorData(dto.error);
                }
            }
            catch (Exception ex)
            {
                dto.error = new Error() { code = -1, msg = ex.Message };
                this.WriteException("UpdatePrice", ex);
            }
            return dto;
        }


        #endregion

        #region 定单类

        /// <summary>
        /// 下发美团配送订单
        /// </summary>
        /// <param name="order_id"></param>
        /// <returns></returns>
        public async Task<DataDto> GetOrderLogisticsPush(long order_id)
        {
            string url = base.BaseAddress.OriginalString + this.urlOrderLogisticsPush + "?";
            url += this.getBaseUrl();
            url += $"&order_id={order_id}";
            url += $"&timestamp={this.timestamp}";

            string sig = this.md5(url + $"{app_secret}");
            url += $"&sig={sig}";
            DataDto dto = null;

            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();
                try
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<DataDto>();
                }
                catch
                {
                    dto = JsonConvert.DeserializeObject<DataDto>(result);

                    DataDto dto2 = (DataDto)dto;
                    this.WriteInformation("GetOrderLogisticsPush", $"code:{dto2.error.code}  msg:{dto2.error.msg}");
                }
            }
            else
            {
                dto = new DataDto();
                dto.error = CreateHttpError(httpResponseMessage);
                this.WriteErrorData(dto.error);
            }
            return dto;
        }

        /// <summary>
        /// 取消美团配送订单
        /// </summary>
        /// <param name="order_id"></param>
        /// <returns></returns>
        public async Task<DataDto> GetOrderLogisticsCancel(long order_id)
        {
            string url = base.BaseAddress.OriginalString + this.urlOrderLogisticsCancel + "?";
            url += this.getBaseUrl();
            url += $"&order_id={order_id}";
            url += $"&timestamp={this.timestamp}";

            string sig = this.md5(url + $"{app_secret}");
            url += $"&sig={sig}";
            DataDto dto = null;

            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();
                try
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<DataDto>();
                }
                catch
                {
                    dto = JsonConvert.DeserializeObject<DataDto>(result);

                    DataDto dto2 = (DataDto)dto;
                    this.WriteInformation("GetOrderLogisticsCancel", $"code:{dto2.error.code}  msg:{dto2.error.msg}");
                }
            }
            else
            {
                dto = new DataDto();
                dto.error = CreateHttpError(httpResponseMessage);
                this.WriteErrorData(dto.error);
            }
            return dto;
        }

        /// <summary>
        /// 获取订单配送状态
        /// </summary>
        /// <returns></returns>
        public async Task<OrderLogisticsDto> GetOrderLogisticsStatus(long order_id)
        {
            OrderLogisticsDto dto = null;

            try
            {
                string url = base.BaseAddress.OriginalString + this.urlOrderLogisticsCancel + "?";
                url += this.getBaseUrl();
                url += $"&order_id={order_id}";
                url += $"&timestamp={this.timestamp}";

                string sig = this.md5(url + $"{app_secret}");
                url += $"&sig={sig}";

                HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string result = await httpResponseMessage.Content.ReadAsStringAsync();
                    try
                    {
                        dto = await httpResponseMessage.Content.ReadAsAsync<OrderLogisticsDto>();
                    }
                    catch
                    {
                        DataDto dto2 = JsonConvert.DeserializeObject<DataDto>(result);
                        dto.error = new Error()
                        {
                            code = dto2.error.code,
                            msg = dto2.error.msg
                        };
                        this.WriteInformation("GetOrderLogisticsStatus", $"code:{dto2.error.code}  msg:{dto2.error.msg}");
                    }
                }
                else
                {
                    dto = new OrderLogisticsDto();
                    dto.error = CreateHttpError(httpResponseMessage);
                    this.WriteErrorData(dto.error);
                }
            }
            catch (Exception ex)
            {
                dto = new OrderLogisticsDto();
                dto.error = new Error() { code = -1, msg = ex.Message };
            }

            return dto;
        }

        /// <summary>
        /// 订单号（同订单展示ID），商家可根据订单号查询订单当前的详细信息。
        /// </summary>
        /// <param name="order_id"></param>
        /// <returns></returns>
        public async Task<OrderDetailDto> GetOrderDetail(long order_id)
        {
            this.GetTimeStamp();

            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("order_id", order_id);

            string url = CreateGetUrl(this.urlGetOrderQuery, values);

            OrderDetailDto result = new OrderDetailDto();
            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                string str = await httpResponseMessage.Content.ReadAsStringAsync();
                result = await httpResponseMessage.Content.ReadAsAsync<OrderDetailDto>();
            }
            return result;
        }

        /// <summary>
        /// 根据流水号获取订单ID（分段）
        /// </summary>
        /// <param name="order_id"></param>
        /// <returns></returns>
        public async Task<OrderIdByDaySeqDto> GetOrderIdByDaySeq(long app_poi_code, int date_time = 0, int day_seq_start = 1, int day_seq_end = 100)
        {
            this.GetTimeStamp();

            if (date_time == 0)
            {
                date_time = int.Parse(DateTime.Now.ToString("yyyyMMdd"));
            }

            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("app_poi_code", app_poi_code);
            values.Add("date_time", date_time);
            values.Add("day_seq_start", day_seq_start);
            values.Add("day_seq_end", day_seq_end);

            string url = CreateGetUrl(this.urlGetOrderIdByDaySeq, values);
 
            OrderIdByDaySeqDto dto = new OrderIdByDaySeqDto();
            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();

                if( result.Contains("\"data\":\"ng\"") )
                {
                    if(!result.Contains("error_list"))
                    {
                        OrderIdByDaySeqDto2 dto2 = await httpResponseMessage.Content.ReadAsAsync<OrderIdByDaySeqDto2>();
                        dto.error = dto2.error;
                    }
                    else
                    {
                        dto.error = new Error() { code = -1};
                    }
                }
                else
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<OrderIdByDaySeqDto>();
                    dto.error = null;
                } 
            }
            return dto;
        }

        #endregion

        #region 账目

        /// <summary>
        /// 获取订单退款记录
        /// </summary>
        /// <param name="wm_order_id_view">订单号</param>
        /// <param name="refund_type">退款类型：1-全额退款；2-部分退款；3-退差价。如不传此字段代表查询全部类型。</param>
        /// <returns></returns>
        public async Task<OrderRefundDetailDto> GetOrderRefundDetail(long wm_order_id_view, int refund_type)
        {
            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("wm_order_id_view", wm_order_id_view);
            values.Add("refund_type", refund_type);

            this.GetTimeStamp();
            string url = CreateGetUrl(this.urlGetOrderRefundDetail, values);

            OrderRefundDetailDto dto = new OrderRefundDetailDto();
            HttpResponseMessage httpResponseMessage = await base.GetAsync(url);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                string result = await httpResponseMessage.Content.ReadAsStringAsync();

                dto = await httpResponseMessage.Content.ReadAsAsync<OrderRefundDetailDto>();
            } 
            return dto;
        }
        #endregion

        #region private

        protected string md5(string str)
        {
            try
            {
                str += this.app_secret;
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                byte[] bytValue, bytHash;
                bytValue = System.Text.Encoding.UTF8.GetBytes(str);
                bytHash = md5.ComputeHash(bytValue);
                md5.Clear();
                string sTemp = "";
                for (int i = 0; i < bytHash.Length; i++)
                {
                    sTemp += bytHash[i].ToString("X").PadLeft(2, '0');
                }
                str = sTemp.ToLower();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            return str;
        }

        protected string getBaseUrl(bool isCode = true)
        {
            string url = "";
            url += $"access_token={this.access_token}";
            url += $"&app_id={app_id}";
            if (isCode)
            {
                url += $"&app_poi_code={this.app_poi_code}";
            }
            return url;
        }

        protected void WriteException(string fun, Exception ex)
        {
            if (this.logger != null)
            {
                this.logger.LogError($"fun:{fun}>> ex:{ex.InnerException.Message}");
            }

        }

        protected void WriteErrorData(Error error)
        {
            if (this.logger != null)
            {
                this.logger.LogInformation($"code:{error.code} msg:{error.msg}");
            }

        }

        protected void WriteInformation(string fun, string msg)
        {
            if (this.logger != null)
            {
                this.logger.LogInformation($"fun:{fun}>> msg:{msg}");
            }
        }

        private string CreateGetUrl(string api, Dictionary<string, object> values)
        {
            values.Add("app_id", this.app_id);
            values.Add("timestamp", this.timestamp);
            values.Add("access_token", this.access_token);

            //创建排序后的字符串
            string url = this.CreateSortParams(values);

            //创建签名
            string urlGet = base.BaseAddress.OriginalString + api + "?" + url;
            string sig = this.md5(urlGet);

            return base.BaseAddress.OriginalString + api + $"?sig={sig}&" + url;

        }

        /// <summary>
        /// 创建Post串 
        /// </summary>
        /// <param name="api"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        private string CreatePostUrl(string api, Dictionary<string, object> values, bool isCode = true)
        {
            values.Add("app_id", this.app_id);
            values.Add("timestamp", this.timestamp);
            values.Add("access_token", this.access_token);
            if (isCode)
            {
                values.Add("app_poi_code", this.app_poi_code);
            }

            //创建排序后的字符串
            string url = base.BaseAddress.OriginalString + api + "?" + this.CreateSortParams(values);

            //创建签名
            string sig = this.md5(url);
            return base.BaseAddress.OriginalString + api + $"?sig={sig}&app_id={this.app_id}&timestamp={this.timestamp}";
        }

        /// <summary>
        /// 排序后的参数
        /// </summary>
        /// <param name="baseUrl"></param>
        /// <param name="keyValues"></param>
        /// <returns></returns>
        private string CreateSortParams(Dictionary<string, object> keyValues)
        {
            //排序字符串
            string[] array = new string[keyValues.Keys.Count];
            keyValues.Keys.CopyTo(array, 0);
            Array.Sort(array);

            string urlValue = "";  //值字符串
            foreach (string key in array)
            {
                if (urlValue != "")
                {
                    urlValue += "&";
                }
                object value = keyValues[key];
                urlValue += $"{key}={value}";
            }

            return urlValue;
            //return base.BaseAddress.OriginalString + baseUrl + "?" + urlValue;
        }

        private HttpContent CreateBody(Dictionary<string, object> values)
        {
            string[] array = new string[values.Keys.Count];
            values.Keys.CopyTo(array, 0);
            Array.Sort(array);

            string urlValue = "";  //值字符串
            foreach (string key in array)
            {
                if (key != "app_id" && key != "timestamp")
                {
                    if (urlValue != "")
                    {
                        urlValue += "&";
                    }

                    object value = values[key];
                    string strValue = System.Web.HttpUtility.UrlEncode(value.ToString(), System.Text.Encoding.UTF8);

                    urlValue += $"{key}={strValue}";
                }
            }

            HttpContent httpContent = new StringContent(urlValue, Encoding.UTF8);
            httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
            return httpContent;
        }

        #endregion


    }
}
